﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Documents;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
using AIStudio.Wpf.DiagramDesigner.Models;
using static System.Net.Mime.MediaTypeNames;

namespace AIStudio.Wpf.DiagramDesigner
{
    public class BlockDesignerItemViewModel : DesignerItemViewModelBase
    {
        public BlockDesignerItemViewModel()
        {
        }

        public BlockDesignerItemViewModel(IDiagramViewModel root) : base(root)
        {
        }

        public BlockDesignerItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {
        }

        public BlockDesignerItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {
        }


        public override SelectableItemBase GetSerializableObject()
        {
            return new BlockDesignerItem(this);
        }

        protected override void InitNew()
        {
            ItemWidth = double.NaN;
            ItemHeight = double.NaN;
            AddConnector(new BlockConnectorInfo(this.Root, this, ConnectorOrientation.Top));
            AddConnector(new BlockConnectorInfo(this.Root, this, ConnectorOrientation.Bottom));
        }

        public override void Init(IDiagramViewModel root, bool initNew)
        {
            base.Init(root, initNew);

            IsReadOnlyText = true;
        }

        protected override void LoadDesignerItemViewModel(SelectableItemBase designerbase)
        {
            base.LoadDesignerItemViewModel(designerbase);

            if (designerbase is BlockDesignerItem designer)
            {
                if (designer.Connectors != null)
                {
                    ClearConnectors();
                    foreach (var connector in designer.Connectors)
                    {
                        BlockConnectorInfo fullyCreatedConnectorInfo = new BlockConnectorInfo(this.Root, this, connector);
                        AddConnector(fullyCreatedConnectorInfo);
                    }
                }

                if (designer.Containers != null)
                {
                    ClearContainers();
                    foreach (var container in designer.Containers)
                    {
                        BlockItemsContainerInfo blockitemsContainerInfo = new BlockItemsContainerInfo(this.Root, this, container);
                        AddContainer(blockitemsContainerInfo);
                    }
                }

                Flag = designer.Flag;
            }
        }

        public void AddNext(BlockDesignerItemViewModel next, BlockDesignerItemViewModel first = null)
        {
            if (LinkNode.Next?.Value == next)
            {
                AlignNext(LinkNode.Next);
                return;
            }

            var linkedList = LinkNode.List;
            var nextlinkedList = next.LinkNode.List;
            if (nextlinkedList == linkedList)//后面的拖到前面去了
            {
                if (first != null)
                {
                    first.RemovePrevious();
                }
                else
                {
                    next.LinkNode.Previous?.Value.RemoveNext();
                }
                nextlinkedList = next.LinkNode.List;
            }
            linkedList.InsertRange(LinkNode, nextlinkedList);
            nextlinkedList.Clear();

            AlignNext(LinkNode.Next);
        }

        public void AlignNext(LinkedListNode<BlockDesignerItemViewModel> nextnode)
        {
            if (nextnode != null && LinkNode.Next == nextnode)
            {
                nextnode.Value.Left = this.Left;
                nextnode.Value.Top = this.Top + this.GetItemHeight();
                if (nextnode.Next != null)
                {
                    nextnode.Value.AlignNext(nextnode.Next);
                }
            }
        }

        public List<BlockDesignerItemViewModel> RemoveNext(bool allbreak = false)
        {
            List<BlockDesignerItemViewModel> removes = new List<BlockDesignerItemViewModel>();
            var next = LinkNode?.Next;
            if (next != null)
            {
                var linkedList = LinkNode.List;

                var list = linkedList.ToList();
                int index = list.IndexOf(next.Value);
                //BlockDesignerItemViewModel[] array = new BlockDesignerItemViewModel[linkedList.Count];
                //linkedList.CopyTo(array, index);

                var nextlinkedList = new LinkedList<BlockDesignerItemViewModel>();
                for (int i = list.Count - 1; i >= index; i--)
                {
                    var nextnode = linkedList.Find(list[i]);
                    linkedList.Remove(nextnode);

                    if (allbreak)//全部变成散落的
                    {
                        list[i].ParentId = new Guid();
                    }
                    else//后面的连接成一个链表
                    {
                        list[i].LinkNode = nextlinkedList.AddFirst(list[i]);
                    }

                    removes.Add(list[i]);
                }

                if (nextlinkedList.First != null)
                {
                    nextlinkedList.First.Value.ParentId = new Guid();
                }
            }

            return removes;
        }

        public List<BlockDesignerItemViewModel> RemoveSelf(bool allbreak = false)
        {
            List<BlockDesignerItemViewModel> removes = new List<BlockDesignerItemViewModel>();
            var linkedList = LinkNode.List;

            var list = linkedList.ToList();
            int index = list.IndexOf(this);

            var nextlinkedList = new LinkedList<BlockDesignerItemViewModel>();
            for (int i = list.Count - 1; i >= index; i--)
            {
                var nextnode = linkedList.Find(list[i]);
                linkedList.Remove(nextnode);

                if (allbreak)//全部变成散落的
                {
                    list[i].ParentId = new Guid();
                }
                else//后面的连接成一个链表
                {
                    list[i].LinkNode = nextlinkedList.AddFirst(list[i]);
                }

                removes.Add(list[i]);
            }

            if (nextlinkedList.First != null)
            {
                nextlinkedList.First.Value.ParentId = new Guid();
            }

            return removes;
        }

        public BlockDesignerItemViewModel RemovePrevious(bool allbreak = false)
        {
            var previous = this.LinkNode.Previous;
            if (previous != null)
            {
                var linkedList = LinkNode.List;
                var previouslinkedList = new LinkedList<BlockDesignerItemViewModel>();

                var list = linkedList.ToList();
                int index = list.IndexOf(previous.Value);
                for (int i = 0; i <= index; i++)
                {
                    var previousnode = linkedList.Find(list[i]);
                    linkedList.Remove(previousnode);
                    if (allbreak)//全部变成散落的
                    {
                        list[i].ParentId = new Guid();
                    }
                    else//前面的连接成一个链表
                    {
                        list[i].LinkNode = previouslinkedList.AddLast(list[i]);
                    }
                }

                this.ParentId = new Guid();
                return previous.Value;
            }
            else
            {
                return null;
            }
        }


        public override void AddToSelection(bool selected, bool clearother)
        {
            if (clearother)
            {
                foreach (SelectableDesignerItemViewModelBase item in Root.SelectedItems.ToList())
                {
                    if (item != this)
                    {
                        item.RemoveFromSelection();
                    }
                }
            }

            IsSelected = selected;
        }

        public virtual void InsertChild(BlockDesignerItemViewModel child, BlockItemsContainerInfo container, int index = -1)
        {
            if (container == null)
            {
                container = FirstContainer;
            }

            if (container.OnlyOneChild)
            {
                var oldchildren = container.Children.FirstOrDefault();
                if (oldchildren != null)
                {
                    this.RemoveChild(oldchildren, container);
                }              
                if (child.LinkNode?.Previous != null)
                {
                    child.LinkNode.Previous.Value.RemoveNext();
                }
                if (child.LinkNode?.Next != null)
                {
                    child.LinkNode.Next.Value.RemovePrevious();
                }
                container.InsertChild(child, index);
                Root.Items.Remove(child);
            }
            else
            {
                var items = new List<BlockDesignerItemViewModel>();
                var linkedList = child.LinkNode.List;

                if (child.LinkNode?.Previous != null)
                {
                    items = child.LinkNode.Previous.Value.RemoveNext(true);
                }
                else
                {
                    items = child.LinkNode.Value.RemoveSelf(true);
                }

                items.ForEach(p => {                    
                    container.InsertChild(p, index++);
                    Root.Items.Remove(p);
                });

            }

            child.RemoveFromSelection();
            this.GetRootContainItem.AddToSelection(true, true);

            System.Windows.Application.Current?.Dispatcher.BeginInvoke(new Action(async () => {
                await Task.Delay(10);
                AlignNext(LinkNode?.Next);
            }));
        }

        public virtual void RemoveChild(BlockDesignerItemViewModel child, BlockItemsContainerInfo container)
        {
            if (container == null)
            {
                container = FirstContainer;
            }
            Root.Items.Add(child);
            container.RemoveChild(child);

            this.RemoveFromSelection();
            child.AddToSelection(true, true);

            System.Windows.Application.Current?.Dispatcher.BeginInvoke(new Action(async () => {
                await Task.Delay(10);
                AlignNext(LinkNode?.Next);
            }));
        }

        private ExecutStatus _executStatus;
        public ExecutStatus ExecutStatus
        {
            get
            {
                return _executStatus;
            }
            set
            {
                SetProperty(ref _executStatus, value);
            }
        }

        public string Flag
        {
            get; set;
        }

        public int LinkNodeLevel
        {
            get
            {
                if (LinkNode?.Previous == null)
                {
                    return 0;
                }
                else
                {
                    return LinkNode.Previous.Value.LinkNodeLevel + 1;
                }
            }
        }

        private LinkedListNode<BlockDesignerItemViewModel> _linkNode;
        public LinkedListNode<BlockDesignerItemViewModel> LinkNode
        {
            get
            {
                if (_linkNode == null || _linkNode.List == null)
                {
                    var linklist = new LinkedList<BlockDesignerItemViewModel>(); ;
                    _linkNode = linklist.AddFirst(this);
                }

                return _linkNode;
            }
            set
            {
                _linkNode = value;
            }
        }

        public BlockDesignerItemViewModel Next
        {
            get
            {
                if (ParentContainer != null)
                {
                    var index = ParentContainer.Children.IndexOf(this);
                    if (index + 1 < ParentContainer.Children.Count)
                    {
                        return ParentContainer.Children[index + 1];
                    }
                    else
                    {
                        return null;
                    }
                }
                else
                {
                    return LinkNode.Next?.Value;
                }
            }
        }

        public BlockDesignerItemViewModel Previous
        {
            get
            {
                if (ParentContainer != null)
                {
                    var index = ParentContainer.Children.IndexOf(this);
                    if (index - 1 >= 0)
                    {
                        return ParentContainer.Children[index - 1];
                    }
                    else
                    {
                        return null;
                    }
                }
                else
                {
                    return LinkNode.Previous?.Value;
                }
            }
        }

        public BlockItemsContainerInfo ParentContainer
        {
            get; set;
        }

        public ObservableCollection<BlockItemsContainerInfo> Containers
        {
            get; set;
        } = new ObservableCollection<BlockItemsContainerInfo>();

        public BlockItemsContainerInfo FirstContainer
        {
            get
            {
                return Containers?.FirstOrDefault();
            }
        }

        public BlockItemsContainerInfo SecondContainer
        {
            get
            {
                return Containers?.Skip(1)?.FirstOrDefault();
            }
        }

        public BlockItemsContainerInfo ThirdContainer
        {
            get
            {
                return Containers?.Skip(2)?.FirstOrDefault();
            }
        }

        public void AddContainer(BlockItemsContainerInfo container)
        {
            Containers.Add(container);
            RaisePropertyChanged(nameof(FirstContainer));
            RaisePropertyChanged(nameof(SecondContainer));
            RaisePropertyChanged(nameof(ThirdContainer));
        }

        public void RemoveContainer(BlockItemsContainerInfo container)
        {
            Containers.Remove(container);
            RaisePropertyChanged(nameof(FirstContainer));
            RaisePropertyChanged(nameof(SecondContainer));
            RaisePropertyChanged(nameof(ThirdContainer));
        }

        public void ClearContainers()
        {
            Containers.Clear();
            RaisePropertyChanged(nameof(FirstContainer));
            RaisePropertyChanged(nameof(SecondContainer));
            RaisePropertyChanged(nameof(ThirdContainer));
        }

        public List<BlockItemsContainerInfo> GetAllContainers()
        {
            return Containers.SelectMany(p => p.GetAllContainers(p.Children, true)).ToList();
        }

        public BlockDesignerItemViewModel GetRootContainItem
        {
            get
            {
                if (ParentContainer == null)
                {
                    return this;
                }
                else
                {
                    return ParentContainer.DataItem.GetRootContainItem;
                }
            }
        }

        #region 执行 
        public override void PreviewExecuteEdit()
        {
            var items = this.LinkNode.List.ToList();

            items.ForEach(p => p.ExecutStatus = ExecutStatus.Preview);
        }

        public override void ExitPreviewExecuteEdit()
        {
            var items = this.LinkNode.List.ToList();

            items.ForEach(p => p.ExecutStatus = ExecutStatus.Stop);
        }

        public virtual Task<bool> Execute()
        {
            return Task.FromResult(true);
        }

        public virtual object GetResult()
        {
            if (FirstContainer != null)
            {
                return FirstContainer.GetResult();
            }
            else if (SecondContainer != null)
            {
                return SecondContainer.GetResult();
            }
            else if (ThirdContainer != null)
            {
                return ThirdContainer.GetResult();
            }
            return null;
        }
        #endregion

        public override void Dispose()
        {
            base.Dispose();

            if (ParentContainer == null)
            {
                foreach (var container in Containers)
                {
                    container.Dispose();
                }
            }
        }
    }

    #region 扩展
    public class BlockContainDesignerItemViewModel : BlockDesignerItemViewModel
    {
        public BlockContainDesignerItemViewModel()
        {
        }

        public BlockContainDesignerItemViewModel(IDiagramViewModel root) : base(root)
        {
        }

        public BlockContainDesignerItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {
        }

        public BlockContainDesignerItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {
        }

        protected override void InitNew()
        {
            base.InitNew();

            Containers.Add(new BlockItemsContainerInfo(this.Root, this, true, null));
        }

    }

    public class BlockContainListDesignerItemViewModel : BlockDesignerItemViewModel
    {
        public BlockContainListDesignerItemViewModel()
        {
        }

        public BlockContainListDesignerItemViewModel(IDiagramViewModel root) : base(root)
        {
        }

        public BlockContainListDesignerItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {
        }

        public BlockContainListDesignerItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {
        }

        protected override void InitNew()
        {
            base.InitNew();

            Containers.Add(new BlockItemsContainerInfo(this.Root, this, false, null));
        }

    }
    #endregion

    #region 帮助
    public class BlockDesignerItemTempLink
    {
        public LinkedList<BlockDesignerItemViewModel> LinkList
        {
            get; set;
        } = new LinkedList<BlockDesignerItemViewModel>();

        public RectangleBase GetBounds()
        {
            return LinkList.FirstOrDefault().GetBounds();
        }

        public List<FullyCreatedConnectorInfo> Connectors
        {
            get
            {
                List<FullyCreatedConnectorInfo> connectors = new List<FullyCreatedConnectorInfo>();
                if (LinkList.FirstOrDefault().TopConnector != null)
                {
                    connectors.Add(LinkList.FirstOrDefault().TopConnector);
                }
                if (LinkList.FirstOrDefault().LeftConnector != null)
                {
                    connectors.Add(LinkList.FirstOrDefault().LeftConnector);
                }
                if (LinkList.LastOrDefault().BottomConnector != null)
                {
                    connectors.Add(LinkList.LastOrDefault().BottomConnector);
                }
                if (LinkList.LastOrDefault().RightConnector != null)
                {
                    connectors.Add(LinkList.LastOrDefault().RightConnector);
                }
                return connectors;
            }
        }

        public static List<BlockDesignerItemTempLink> Build(List<BlockDesignerItemViewModel> blocks)
        {
            List<BlockDesignerItemTempLink> links = new List<BlockDesignerItemTempLink>();

            foreach (var blockgroup in blocks.GroupBy(p => p.LinkNode.List))
            {
                var link = new BlockDesignerItemTempLink();
                foreach (var block in blockgroup.OrderBy(p => p.LinkNodeLevel))
                {
                    link.LinkList.AddLast(block);
                }
                links.Add(link);
            }
            return links;
        }
    }
    #endregion

    public enum ExecutStatus
    {
        Stop,
        Run,
        Pause,
        Preview,
    }
}
